// debug.hpp
#pragma once

#include <iostream>
#include <string_view>
#include <utility>
#include <filesystem> // 新增
#include <chrono>     // 新增
#include <iomanip>    // 新增
#include <sstream>    // 新增
#include <mutex>      // 新增，用于线程安全

#ifdef _WIN32
#include <io.h>
#define isatty _isatty
#define fileno _fileno
#else
#include <unistd.h>
#endif

// 定义调试级别
enum class DebugLevel
{
  Off = 0,
  Error = 1,
  Warning = 2,
  Info = 3,
  Debug = 4
};

// 定义颜色代码枚举
enum class ColorCode
{
  Reset = 0,
  Red,
  Yellow,
  Green,
  Blue
};

// 使用 CMake 定义的调试级别
#ifndef CURRENT_DEBUG_LEVEL
#define CURRENT_DEBUG_LEVEL 0 // 默认为 Off
#endif

constexpr DebugLevel RUNTIME_DEBUG_LEVEL = static_cast<DebugLevel>(CURRENT_DEBUG_LEVEL);

// 定义是否使用颜色输出的宏
#ifndef USE_COLOR_OUTPUT
#define USE_COLOR_OUTPUT 1
#endif

// 检查是否为终端输出
// inline bool is_terminal_output()
// {
//   return isatty(fileno(stdout)) != 0;
// }

inline bool is_terminal_output()
{
  return true;
}

// 辅助函数：将 DebugLevel 转换为字符串
constexpr const char *debug_level_to_string(DebugLevel level)
{
  switch (level)
  {
  case DebugLevel::Error:
    return "ERR";
  case DebugLevel::Warning:
    return "WAR";
  case DebugLevel::Info:
    return "INF";
  case DebugLevel::Debug:
    return "DEB";
  default:
    return "UNKNOWN";
  }
}

// 辅助函数：获取日志级别对应的颜色代码
constexpr ColorCode get_color_code(DebugLevel level)
{
  switch (level)
  {
  case DebugLevel::Error:
    return ColorCode::Red;
  case DebugLevel::Warning:
    return ColorCode::Yellow;
  case DebugLevel::Info:
    return ColorCode::Green;
  case DebugLevel::Debug:
    return ColorCode::Blue;
  default:
    return ColorCode::Reset;
  }
}

// 辅助函数：将颜色代码转换为ANSI转义序列
constexpr const char *color_code_to_ansi(ColorCode code)
{
  switch (code)
  {
  case ColorCode::Red:
    return "\033[0;31m";
  case ColorCode::Yellow:
    return "\033[0;33m";
  case ColorCode::Green:
    return "\033[0;32m";
  case ColorCode::Blue:
    return "\033[0;34m";
  case ColorCode::Reset:
    return "\033[0m";
  default:
    return "";
  }
}

// 运行时处理颜色输出
inline const char *get_color_output(ColorCode code)
{
  if (USE_COLOR_OUTPUT && is_terminal_output())
  {
    return color_code_to_ansi(code);
  }
  return "";
}

// 辅助函数：提取文件名
inline std::string get_filename(const char *filepath)
{
  return std::filesystem::path(filepath).filename().string();
}

// 辅助函数：获取当前时间戳（精确到纳秒）
inline std::string get_current_timestamp()
{
  // 获取当前时间点
  auto now = std::chrono::system_clock::now();

  // 转换为 time_t 以获取秒级时间
  auto itt = std::chrono::system_clock::to_time_t(now);

  // 获取纳秒部分
  auto duration = now.time_since_epoch();
  auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
  auto sub_seconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - seconds); // 改为纳秒

  // 转换为 tm 结构
  std::tm tm;
#ifdef _WIN32
  localtime_s(&tm, &itt);
#else
  localtime_r(&itt, &tm);
#endif

  // 格式化时间字符串并添加纳秒部分
  std::ostringstream ss;
  ss << std::put_time(&tm, "%H:%M:%S")
     << '.' << std::setfill('0') << std::setw(9) << sub_seconds.count(); // 改为9位表示纳秒
  return ss.str();
}

// 定义互斥锁，确保多线程环境下的日志输出安全
inline std::mutex log_mutex;

// 基础日志函数
template <DebugLevel Level, typename... Args>
void log_base(const char *file, int line, bool include_location, std::string_view format, Args &&...args)
{
  std::ios::sync_with_stdio(false);
  if constexpr (static_cast<int>(Level) <= CURRENT_DEBUG_LEVEL)
  {
    std::lock_guard<std::mutex> lock(log_mutex); // 锁定，确保线程安全
    std::cout << get_color_output(get_color_code(Level))
              << "[" << debug_level_to_string(Level) << "]"
              << " [" << get_current_timestamp() << "]"; // 添加时间戳
    if (include_location)
    {
      std::cout << " [" << get_filename(file) << ":" << line << "] "; // 仅显示文件名
    }
    std::cout << std::fixed << std::setprecision(9);
    std::cout << format;
    ((std::cout << ' ' << std::forward<Args>(args)), ...);
    std::cout << get_color_output(ColorCode::Reset) << std::endl;
    std::cout.flush(); // 确保输出被刷新
  }
}

// 宏封装，简化调用
#define LOG_ERROR(...) log_base<DebugLevel::Error>(__FILE__, __LINE__, true, __VA_ARGS__)
#define LOG_WARN(...) log_base<DebugLevel::Warning>(__FILE__, __LINE__, true, __VA_ARGS__)
#define LOG_INFO(...) log_base<DebugLevel::Info>(__FILE__, __LINE__, true, __VA_ARGS__)
#define LOG_DEBUG(...) log_base<DebugLevel::Debug>(__FILE__, __LINE__, true, __VA_ARGS__)

// 条件编译宏，用于在编译时完全移除不需要的日志代码
#if CURRENT_DEBUG_LEVEL >= 4
#define DEBUG_CODE(x) x
#else
#define DEBUG_CODE(x)
#endif

#if CURRENT_DEBUG_LEVEL >= 3
#define INFO_CODE(x) x
#else
#define INFO_CODE(x)
#endif

#if CURRENT_DEBUG_LEVEL >= 2
#define WARNING_CODE(x) x
#else
#define WARNING_CODE(x)
#endif

#if CURRENT_DEBUG_LEVEL >= 1
#define ERROR_CODE(x) x
#else
#define ERROR_CODE(x)
#endif
